package com.ruoyi.web.controller.common;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.admin.domain.Sensor;
import com.ruoyi.admin.mapper.SensorMapper;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class DataController implements MqttCallback {

    public static final String HOST = "tcp://106.227.89.45:1883"; // MQTT Broker URL
    private static final String clientID = "clientXX"; // MQTT Client ID
    private String TOPIC = "nongye"; // MQTT Topic to subscribe
    private MqttClient client;
    private MqttConnectOptions options;
    private String user = "nongye"; // MQTT Username
    private String password = "nongye"; // MQTT Password
    private static final int MAX_RECONNECT_ATTEMPTS = 10; // 最大重连尝试次数
    private static final int RECONNECT_DELAY_SECONDS = 5; // 重连间隔时间（秒）
    private List<Sensor> sensorDataList = new ArrayList<>();

    @Autowired
    public SensorMapper sensorMapper;
    /* 连接MQTT */
    @PostConstruct
    public void clientStart() {
        try {
            client = new MqttClient(HOST, clientID, new MemoryPersistence());
            options = new MqttConnectOptions();
            options.setCleanSession(true);
            options.setKeepAliveInterval(10);
            options.setConnectionTimeout(50);
            options.setUserName(user);
            options.setPassword(password.toCharArray());
            client.setCallback(this);
            client.connect(options);
            int[] Qos = {1}; // QoS 1 ensures at least once delivery
            String[] topic1 = {TOPIC};
            client.subscribe(topic1, Qos);
            //System.out.println("Connected to MQTT Broker and subscribed to topic: " + TOPIC);
        } catch (MqttException e) {
//            e.printStackTrace();
//            System.out.println("Failed to connect to MQTT Broker: " + e.getMessage());
        }
    }

    @Override
    public void connectionLost(Throwable throwable) {
        //  System.out.println("Connection lost: " + throwable.getMessage());
        // 重新连接逻辑
        reconnect();
    }

    // 重新连接方法
    private void reconnect() {
        int attempt = 0;
        while (true) { //无限重连
            try {
                if (client != null && !client.isConnected()) {
                    client.connect(options);
                    client.subscribe(TOPIC, 1);
                    //System.out.println("Reconnected to MQTT Broker and subscribed to topic: " + TOPIC);
                    return;
                }
            } catch (MqttException e) {
                //e.printStackTrace();
                //System.out.println("Failed to reconnect to MQTT Broker: " + e.getMessage());
            }
            // attempt++;
            try {
                //  System.out.println("Retrying connection in " + RECONNECT_DELAY_SECONDS + " seconds...");
                TimeUnit.SECONDS.sleep(RECONNECT_DELAY_SECONDS);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                // System.out.println("Reconnect thread interrupted: " + ie.getMessage());
                return;
            }
        }
        // System.out.println("Max reconnect attempts reached. Stopping reconnection.");
    }

    // 接收MQTT上订阅主题的数据
    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        try {
            String msg = new String(mqttMessage.getPayload());
            // System.out.println("Received message from topic: " + topic);
            //System.out.println("Message: " + msg);

            // 解析JSON消息
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(msg);

            JsonNode dataList = jsonNode.get("data");
            if (dataList.isArray()) {
                for (JsonNode dataNode : dataList) {
                    String name = dataNode.get("name").asText();
                    double value = dataNode.get("value").asDouble();
                    int sensorNumber = 0;

                    if (name.startsWith("trwd")) {
                        sensorNumber = Integer.parseInt(name.substring(4));
                        updateSensor(sensorNumber, "temperature", value);
                    } else if (name.startsWith("trsd")) {
                        sensorNumber = Integer.parseInt(name.substring(4));
                        updateSensor(sensorNumber, "humidity", value);
                    } else if (name.startsWith("trN")) {
                        sensorNumber = Integer.parseInt(name.substring(3));
                        updateSensor(sensorNumber, "soilN", value);
                    } else if (name.startsWith("trL")) {
                        sensorNumber = Integer.parseInt(name.substring(3));
                        updateSensor(sensorNumber, "soilP", value);
                    } else if (name.startsWith("trK")) {
                        sensorNumber = Integer.parseInt(name.substring(3));
                        updateSensor(sensorNumber, "soilK", value);
                    }
                }

                // 提取时间戳并设置到所有传感器对象中
                long ts = jsonNode.get("ts").asLong();
                Date timestamp = new Date(ts * 1000); // Convert timestamp to Date
                for (Sensor sensor : sensorDataList) {
                    sensor.setTimestamp(timestamp);
                }

                // 输出整合后的数据
                for (Sensor sensor : sensorDataList) {
                    sensorMapper.insertSensor(sensor);
                    log.info("处理后的senson对象:{}",sensor);
                }
            }



            long ts = jsonNode.get("ts").asLong();
            Date date = new Date(ts * 1000); // Convert timestamp to Date
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Timestamp: " + sdf.format(date));
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Failed to process message: " + e.getMessage());
        }
    }

    private void updateSensor(int sensorNumber, String sensorType, double value) {
        Sensor sensor = findSensorByNumber(sensorNumber);
        if (sensor == null) {
            sensor = new Sensor();
            sensor.setName("传感器" + sensorNumber);
            sensorDataList.add(sensor);
        }

        switch (sensorType) {
            case "temperature":
                sensor.setTemperature((long) value);
                break;
            case "humidity":
                sensor.setHumidity((long) value);
                break;
            case "soilN":
                sensor.setSoilN((long) value);
                break;
            case "soilP":
                sensor.setSoilP((long) value);
                break;
            case "soilK":
                sensor.setSoilK((long) value);
                break;
        }
    }

    private Sensor findSensorByNumber(int sensorNumber) {
        for (Sensor sensor : sensorDataList) {
            if (sensor.getName().equals("传感器" + sensorNumber)) {
                return sensor;
            }
        }
        return null;
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        // Not used in this example
    }

    // 获取传感器数据列表
    public List<Sensor> getSensorDataList() {
        return sensorDataList;
    }
}
